package com.google.code.scalaxmljaxen

import org.jaxen.DefaultNavigator
import org.jaxen.JaxenConstants

import scala.xml._

import scala.collection.jcl.ArrayList

import lcj._

class DocumentNavigator extends DefaultNavigator {
  /** Iterator used by Navigator */
  type It = java.util.Iterator[Any]
  
  private implicit def iterableToJavaIterator[T](c: Iterable[T]) = new lcj.IteratorWrapper[T](c.elements)
  
  override def getNamespacePrefix(any: AnyRef) = "" // XXX
  
  override def isElement(any: AnyRef) = any.isInstanceOf[Elem]
  
  override def isComment(any: AnyRef) = any.isInstanceOf[Comment]
  
  override def isText(any: AnyRef) = any.isInstanceOf[Text]
  
  override def isAttribute(any: AnyRef) = any.isInstanceOf[MetaData]
  
  override def isProcessingInstruction(any: AnyRef) = any.isInstanceOf[ProcInstr]
  
  override def isDocument(any: AnyRef) = any.isInstanceOf[Document]
  
  override def isNamespace(any: AnyRef) = false // XXX
  
  override def getElementName(any: AnyRef) = any match {
    case Elem(_, name, _, _, _*) => name
  }
  
  override def getElementNamespaceUri(any: AnyRef) = "" // XXX
  
  override def getElementQName(any: AnyRef) = null // XXX
  
  override def getAttributeName(any: AnyRef) = any match {
    case md: MetaData => md.key
    case _ => null
  }
  
  override def getAttributeNamespaceUri(any: AnyRef) = null // XXX
  
  override def getAttributeQName(any: AnyRef) = null // XXX
  
  override def getChildAxisIterator(any: AnyRef): It = any match {
    case Elem(_, _, _, _, children @ _*) => children
    case _ => IteratorWrapper.empty
  }
  
  // XXX: override
  def getChildAxisIterator(contextNode: AnyRef, localName: String, namespacePrefix: String, namespaceURI: String): It = {
    contextNode match {
      // XXX: ns is ignored
      case ns: NodeSeq => ns \ localName
      case _ => IteratorWrapper.empty
    }
  }
  
  // Seems like Scala stuff has no parents
  override def getParentAxisIterator(contextNode: AnyRef) = IteratorWrapper.empty
  
  override def getAttributeAxisIterator(contextNode: AnyRef): It = contextNode match {
    case Elem(_, _, attributes, _, _*) => attributes
    case _ => IteratorWrapper.empty
  }
  
  // XXX: overrides
  def getAttributeAxisIterator(contextNode: AnyRef, localName: String, namespacePrefix: String, namespaceURI: String) =
    contextNode match {
      case Elem(_, _, attributes, _, _*) => attributes.get(localName).toList
      case _ => IteratorWrapper.empty // XXX: not yet
    }
  
  override def getNamespaceAxisIterator(contextNode: AnyRef) = IteratorWrapper.empty // XXX
  
  override def getDocumentNode(contextNode: AnyRef) = null
  
  override def parseXPath(expr: String) = new ScalaXmlXPath(expr)
  
  override def getParentNode(contextNode: AnyRef) = null
  
  override def getTextStringValue(any: AnyRef) = getNodeStringValue(any)
  
  override def getElementStringValue(any: AnyRef) = getNodeStringValue(any)
  
  override def getAttributeStringValue(any: AnyRef) = any match {
    case md: MetaData => md.value.text
    case _ => null
  }
  
  /*
  private def string(ns: NodeSeq): String = ns match {
    case t: Text => t.data.trim
    case Elem(_, _, _, _, children @ _*) => children.map(string).mkString("")
    case x => x.elements.map(string).mkString("")
  }
  */
  
  private def string(ns: NodeSeq): String = ns.text
    
  private def getNodeStringValue(any: AnyRef) = any match {
    case ns: NodeSeq => string(ns)
  }
  
  override def getNamespaceStringValue(any: AnyRef) = "" // XXX
  
  override def getCommentStringValue(ns: AnyRef) = ns match {
    case c: Comment => c.text
  }
}

object DocumentNavigator extends DocumentNavigator

// vim: set ts=2 sw=2 et:
